package com.amadeus.spin.devtool.soap.shooter.process;

import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * This class deals with XSD operations.
 * 
 */
public class XSDHelper {

  private static Logger logger = Logger.getLogger(XSDHelper.class);

  private static final String IS_STRUCTURED_XML = "IS_STRUCTURED_XML";

  public XSDHelper() {
  }

  /**
   * Checks weither the XSD specifies the tag IS_STRUCTURED_XML. Default is false
   * 
   * @param xsd
   * @return
   */
  public boolean isElligibleToStructuredTag(String xsd) {
    boolean elligible = false;
    if (xsd != null) {
      logger.debug("Processing xsd file to find if the scenario should be structured : " + xsd);
      try {
        // open the XSD file
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();

        Document doc = builder.parse(xsd);
        // Element root = doc.getgetDocumentElement();
        // Check the actual file content
        if (containsStructuredXml(doc.getElementsByTagName("xsd:element"))) {
          return true;
        }

        // First check the includes of the XSD
        NodeList includes = doc.getElementsByTagName("xsd:include");
        for (int k = 0; includes != null && k < includes.getLength(); k++) {
          if (isElligibleToStructuredTag(StringUtils.substringBeforeLast(xsd, "/") + "/" +
              ((Element)includes.item(k)).getAttribute("schemaLocation"))) {
            return true;
          }
        }
      }
      catch (Exception e) {
        logger.error("Could not inspect xsd " + xsd, e);
      }
    }
    return elligible;
  }

  /**
   * Checks if the list of nodes contains the tag IS_STRUCTURED_XML
   *
   * @param list
   * @return
   */
  private boolean containsStructuredXml(NodeList nList) {
    boolean result = false;
    for (int i = 0; i < nList.getLength(); i++) {
      if (IS_STRUCTURED_XML.equals(((Element)nList.item(i)).getAttribute("name"))) {
        result = true;
      }
    }
    return result;
  }

  /**
   * Returns the xsd from an xml
   * 
   * @param xmlContent
   * @return
   */
  String getXsdFromXml(String xmlContent) {
    String xsd = null;
    try {
      DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder;
      builder = fact.newDocumentBuilder();
      Document doc;
      StringReader reader = new StringReader(xmlContent);
      InputSource inputSource = new InputSource(reader);
      doc = builder.parse(inputSource);
      Element node = doc.getDocumentElement();
      xsd = node.getAttribute("xsi:noNamespaceSchemaLocation");
    }
    catch (ParserConfigurationException e) {
      logger.error("Could not inspect XSD value ", e);
    }
    catch (SAXException e) {
      logger.error("Could not parse input ", e);
    }
    catch (IOException e) {
      logger.error("Could not open input", e);
    }
    return xsd;
  }
}